#include "stdafx.h"

#include "../inc/vipf.h"
#include <stdio.h>
#include <stdlib.h>

#ifdef WIN32
#include <winsock.h>
#else
#include <sys/types.h> 
#include <sys/stat.h>
#include <sys/wait.h>
#include <sys/socket.h> 
#include <netinet/in.h>
#include <arpa/inet.h>
#endif

#include <malloc.h>
#include <string.h>
FILE * vipf_open(const char *filename,const char *mode)
{
    FILE * ret; 
	if ((ret = fopen(filename, mode)) == NULL) {
      fprintf(stderr, "couldn't open file!\n");
      return NULL;
    }
	return ret;
}

int vipf_create_head(FILE *vipffile,unsigned short width,unsigned short height,const char *encode)
{

    if(fseek(vipffile,0,SEEK_SET))
	{
		#ifdef DEBUG
        fprintf(stderr, "vipf_create_head: seek file head error!\n");
        #endif 
        return -1;
	}

	struct VIPF_file_head fhead ={
		{'V','I','P','F'},
		{'M','J','P','G'},
		htons(width),
		htons(height)
	};

    if(encode != NULL)
	{
		memcpy(fhead.compression,encode,4);
	}

	if( fwrite(&fhead,1,sizeof(struct VIPF_file_head),vipffile) != sizeof(struct VIPF_file_head))
    {
	    #ifdef DEBUG
        fprintf(stderr, "vipf_create_head: write file head error!\n");
        #endif 
        return -1;
	}

	return sizeof(struct VIPF_file_head);
}

int vipf_write(FILE *vipffile, void *data_buff, unsigned int data_length,unsigned long timestamp,unsigned long seq,VIPF_BTYPE btype)
{
	unsigned int jpg_length_align;
	unsigned int mfsz, remnant;
	char fillbuf[4];
	//add by owen, to return bytes written.
	unsigned int bytes = 0;
	memset(fillbuf,0,4);

	struct VIPF_block_head bhead = {
		{'V','I','P','V'},
		htonl(timestamp),
		htonl(seq),
		htonl(data_length)
	};
	
    switch(btype)
	{
	case VIDEO_TYPE:
		memcpy(bhead.bh_id,"VIPV",4);
		break;
	case AUDIO_TYPE:
		memcpy(bhead.bh_id,"VIPA",4);
		break;
	case SUBT_TYPE:
		memcpy(bhead.bh_id,"VIPS",4);
		break;
	default:
#ifdef DEBUG
        fprintf(stderr, "vipf_write:  block type error!\n");
#endif 
        return -1;
	}
	
	mfsz = data_length;
    remnant = 4-(mfsz%4);
	jpg_length_align = mfsz + remnant;
    bhead.data_sz = htonl(jpg_length_align);
	bytes = sizeof(struct VIPF_block_head);
	if( fwrite(&bhead,1,bytes,vipffile) != bytes)
    {
	    #ifdef DEBUG
        fprintf(stderr, "vipf_write: write block head error!\n");
        #endif 
        return -1;
	}

	if( fwrite(data_buff,1,data_length,vipffile) != data_length )
    {
	    #ifdef DEBUG
        fprintf(stderr, "vipf_write: write frame data error!\n");
        #endif 
        return -1;
	}
	bytes += data_length;
	if (remnant > 0) 
	{
	   if( fwrite(fillbuf,1,remnant,vipffile) != remnant )
	   {
			#ifdef DEBUG
			fprintf(stderr, "vipf_write: fill remnant data error!\n");
			#endif 
			return -1;
	   }
	   bytes += remnant;
    }

	fflush(vipffile);

    return bytes;
}

void vipf_close(FILE * vipffile)
{
	fclose(vipffile);
}

int vipf_read_head(struct VIPF_file_head *fh,FILE *vipffile)
{
	unsigned long rn;
    struct VIPF_file_head buf;


	if( (rn=fread(&buf,1,sizeof(struct VIPF_file_head),vipffile)) < sizeof(struct VIPF_file_head) )
	{
		#ifdef DEBUG
        fprintf(stderr, "vipf_read_head:read file head error!\n");
        #endif
		return -1;
	}

    if(buf.fh_id[0]!='V' || 
	   buf.fh_id[1]!='I' || 
	   buf.fh_id[2]!='P' ||
	   buf.fh_id[3]!='F'   )
	{
		#ifdef DEBUG
		fprintf(stderr,"vipf_read_head:file ID error!\n");
        #endif
		return -1;
	}

	memcpy(fh->fh_id,&buf,8);

	fh->width = ntohs(buf.width);
	fh->height = ntohs(buf.height);
	return 0;
}


int vipf_next_frame(void *ptr,struct VIPF_block_head *bh,FILE *vipffile, bool bReadData)
{
    unsigned long rn;
	unsigned long dsz;
    struct VIPF_block_head buf;
	char id[4];

	if( (rn=fread(&buf,1,sizeof(struct VIPF_block_head),vipffile)) < sizeof(struct VIPF_block_head) )
	{
		if(feof(vipffile))
		{
	        #ifdef DEBUG
			//fprintf(stderr, "vipf_next_frame:read the end of file!\n");
			#endif
		    return -2;
		}
		#ifdef DEBUG
        fprintf(stderr, "vipf_next_frame:read block head error!rn==%d\n",rn);
		#endif
		return -1;
		
	}
    
	memcpy(id,buf.bh_id,4);
	if( strncmp(id,"VIP",3) ) //the first three char should be "VIP"
	{
#ifdef DEBUG
		fprintf(stderr,"vipf_next_frame: block ID error!\n");
#endif
		return -1;
	}
	
	
	if( id[3]!='V' && id[3]!='A' && id[3]!='S') //the last char should be 'V' or 'A' or 'S'
	{
		#ifdef DEBUG
		fprintf(stderr,"vipf_next_frame: block ID error!\n");
		#endif
		return -1;
	}

	memcpy(bh,&buf,4);
    dsz = ntohl(buf.data_sz);
	bh->data_sz = dsz;
	bh->seq = ntohl(buf.seq);
	bh->timestamp = ntohl(buf.timestamp);
	
	if (bReadData)
	{
		if( (rn=fread(ptr,1,dsz,vipffile)) < dsz )
		{
			#ifdef DEBUG
			fprintf(stderr, "vipf_next_frame:read block data error!\n");
			#endif
			return -1;
		}
	}
	else
	{
		if (fseek(vipffile, dsz, SEEK_CUR) != 0)
		{
			#ifdef DEBUG
			fprintf(stderr, "vipf_next_frame:seek error!\n");
			#endif
			return -1;
		}
	}

	return 0;
}


int vipf_read_frame(void *ptr,unsigned long frame_number,struct VIPF_block_head *bh,FILE *vipffile,VIPF_BTYPE btype)
{
    unsigned long rn ;
	unsigned long dsz;
	unsigned long i;
    struct VIPF_block_head buf;
    //the first frame is zero
	char id[4];

	if(fseek(vipffile,sizeof(struct VIPF_file_head),SEEK_SET) < 0)
	{
		#ifdef DEBUG
		fprintf(stderr, "vipf_read_frame:seek file head error,can't find frame!\n");
		#endif
		return -1;
	}
	
	memset(id,0,4);
	switch(btype)
	{
	case VIDEO_TYPE:
		memcpy(id,"VIPV",4);
		break;
	case AUDIO_TYPE:
		memcpy(id,"VIPA",4);
		break;
	case SUBT_TYPE:
		memcpy(id,"VIPS",4);
		break;
	default:
#ifdef DEBUG
        fprintf(stderr, "vipf_read_frame: input block type error!\n");
#endif 
        return -1;
	}

	for( i=0;i<=frame_number;)//search appointed frame
	{
		if( (rn=fread(&buf,1,sizeof(struct VIPF_block_head),vipffile)) < sizeof(struct VIPF_block_head) )
		{
			#ifdef DEBUG
			fprintf(stderr, "vipf_read_frame: read block head error,can't find frame!\n");
            #endif
			return -1;
		}
		
		if( strncmp((char *)buf.bh_id,id,4)==0)
		{
			
			if(i==frame_number)
				break;
			else
				i++;
		}
		
		if(fseek(vipffile,ntohl(buf.data_sz),SEEK_CUR) < 0)
		{
			#ifdef DEBUG
			fprintf(stderr, "vipf_read_frame: seek block error,can't find frame!\n");
			#endif
			return -1;
		}
	}
	
	if(frame_number != ntohl(buf.seq))
	{
		#ifdef DEBUG
		fprintf(stderr,"vipf_read_frame:frame_number no match fram seq,can't find frame!\n");
		#endif
		return -1;
	}
	
	memcpy(bh,&buf,4);
	dsz = ntohl(buf.data_sz);
	bh->data_sz = dsz;
	bh->seq = ntohl(buf.seq);
	bh->timestamp = ntohl(buf.timestamp);
	
	if((rn=fread(ptr,1,dsz,vipffile)) < dsz )
	{
		#ifdef DEBUG
		fprintf(stderr, "vipf_read_frame: found frame, but read block data error!\n");
		#endif
		return -1;
	}
	return 0;
}




    




	

